/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package abricots.net;

import abricots.net.common.AckedFramesManager;
import abricots.net.common.ConnectionProvider;
import abricots.net.common.GameMessage;
import abricots.net.common.NetUtils;
import abricots.net.common.NetUtils.GameClientListener;
import abricots.net.common.PaquetProcessor;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 *
 * @author charly
 */
public class GameClient implements ConnectionProvider {
   private Client kryoClient;
   private Set<GameClientListener> listeners;
   private PaquetProcessor paquetProcessor;
   private Connection connection;
   private AckedFramesManager ackedFramesManager;

   public GameClient() {
      listeners = new HashSet<GameClientListener>();
      paquetProcessor = new PaquetProcessor(this);
      ackedFramesManager = new AckedFramesManager();
   }

   public void startClient() {
      kryoClient = new Client();
      NetUtils.registerClasses(kryoClient);
      kryoClient.start();
      kryoClient.addListener(paquetProcessor);
   }

   public void connect() {
      Runnable connectRunnable = new Runnable() {
         @Override
         public void run() {
            try {
               kryoClient.connect(5000, "127.0.0.1", NetUtils.TCP_PORT, NetUtils.UDP_PORT);
            } catch (IOException ex) {
               fireConnectionFailed();
            }
         }
      };
      new Thread(connectRunnable).start();
   }

   private void fireConnectionFailed() {
      for (GameClientListener listener : listeners) {
         listener.connectionFailed();
      }
   }

   public void update(int delta) {
      try {
         kryoClient.update(delta);
      } catch (IOException ex) {
      }
   }

   public void addListener(GameClientListener clientListener) {
      listeners.add(clientListener);
   }

   public void removeListener(GameClientListener clientListener) {
      listeners.remove(clientListener);
   }

   @Override
   public int send(Object message) {
      GameMessage gameMessage = paquetProcessor.processOut(message);
      kryoClient.sendUDP(gameMessage);
      return gameMessage.id;
   }

   @Override
   public void onMessageReceived(GameMessage message) {
      ackedFramesManager.newAckedState(message.ackId);
      for (GameClientListener listener : listeners) {
         listener.messageReceived(message, connection);
      }
   }

   @Override
   public void onConnection(Connection connection) {
      this.connection = connection;
      for (GameClientListener listener : listeners) {
         listener.onConnection(connection);
      }
   }

   @Override
   public void onDisconnection(Connection connection) {
   }

   public AckedFramesManager getAckedFramesManager() {
      return ackedFramesManager;
   }
}
